package com.web.js;

import static com.metrics.utils.FormatNumberUtil.*;

import static com.web.utils.SingletonData.*;
import java.util.*;

import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;

import com.database.daos.IProjectDao;
import com.database.objects.*;
import com.metrics.ctrls.IModelCtrl;
import com.metrics.objects.Metric;
import com.web.utils.SingletonData;

public class ModelJS {

	private static final String SEPARATOR = "%%";

	private static final String OUTLIER_MARK = "**";

	private IProjectDao projectDao;

	private IModelCtrl modelCtrl;

	private SingletonData singletonData;

	public String[] getModelResult(String projectName, String[] metricsSize, Double[] weightsSize, String[] metricsQuality, Double[] weightsQuality) {
		Project project = projectDao.getByName(projectName);

		Map<Developer, Double> factorSize = calculateFactor(project.getDevelopers(), metricsSize, weightsSize);
		Map<Developer, Double> factorQuality = calculateFactor(project.getDevelopers(), metricsQuality, weightsQuality);

		Double percentilSize = getPercentil(factorSize.values(), 75);
		Double percentilQuality = getPercentil(factorQuality.values(), 75);

		String valueData = "";
		String[] result = new String[project.getNumberDevelopers() + 1];
		int i = 0;
		for (Developer developer : factorSize.keySet()) {
			Double size = factorSize.get(developer);
			Double quality = factorQuality.get(developer);

			boolean addSizeMark = size >= percentilSize ? true : false;
			boolean addQualityMark = quality >= percentilQuality ? true : false;

			String textSize = (addSizeMark ? OUTLIER_MARK : "") + formatTextToFourDecimals(size * 100);
			String textQuality = (addQualityMark ? OUTLIER_MARK : "") + formatTextToFourDecimals(quality * 100);
			String data = developer.getName() + SEPARATOR + textSize + SEPARATOR + textQuality;

			result[i] = data;
			valueData += data.replace(OUTLIER_MARK, "") + SEPARATOR_1;
			i++;
		}

		Integer key = singletonData.setValue(valueData.substring(0, valueData.length() - SEPARATOR_1.length()));
		result[result.length - 1] = key.toString();
		return result;
	}

	private Map<Developer, Double> calculateFactor(List<Developer> developers, String[] metricsArray, Double[] weights) {
		Map<Developer, Double> factorMap = new TreeMap<Developer, Double>();

		Metric[] metrics = extractMetrics(metricsArray);
		Status[] status = extractStatus(metricsArray);
		Type[] types = extractTypes(metricsArray);

		for (Developer developer : developers) {
			Double value = modelCtrl.calculateModel(developer, metrics, status, types, weights);
			factorMap.put(developer, value);
		}

		return factorMap;
	}

	private Metric[] extractMetrics(String[] metricsPage) {
		Metric[] metrics = new Metric[metricsPage.length];
		for (int i = 0; i < metrics.length; i++) {
			String text = metricsPage[i].split(" OF ")[0];
			metrics[i] = Metric.valueOfText(text);
		}
		return metrics;
	}

	private Status[] extractStatus(String[] metrics) {
		Status[] status = new Status[metrics.length];
		for (int i = 0; i < status.length; i++) {
			String secondToken = metrics[i].split(" OF ")[1];
			String text = secondToken.split(" ")[0];
			status[i] = Status.valueOfText(text);
		}
		return status;
	}

	private Type[] extractTypes(String[] metrics) {
		Type[] types = new Type[metrics.length];
		for (int i = 0; i < types.length; i++) {
			String secondToken = metrics[i].split(" OF ")[1];
			types[i] = Type.valueOfText(secondToken.substring(secondToken.indexOf(" ") + 1));
		}
		return types;
	}

	private Double getPercentil(Collection<Double> values, int numPercentil) {
		DescriptiveStatistics statistics = new DescriptiveStatistics();
		for (Double value : values) {
			statistics.addValue(value);
		}
		return statistics.getPercentile(numPercentil);
	}

	public void setProjectDao(IProjectDao projectDao) {
		this.projectDao = projectDao;
	}

	public void setModelCtrl(IModelCtrl modelCtrl) {
		this.modelCtrl = modelCtrl;
	}

	public void setSingletonData(SingletonData singletonData) {
		this.singletonData = singletonData;
	}

}